package com.xbongbong.workflow.service.strategy.data.impl;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.log.constant.CrmLogMemoConstant;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.customercommunicate.pojo.dto.CustomerDynamicAddDTO;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.message.pojo.dto.ConsistencySyncRabbitMqDTO;
import com.xbongbong.pro.service.toolbox.statistic.help.ChartQueryHelp;
import com.xbongbong.pro.service.toolbox.statistic.help.FormHelp;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.CustomerStatementEntity;
import com.xbongbong.saas.domain.entity.ext.PaymentEntityExt;
import com.xbongbong.saas.enums.CustomerStatementEnum;
import com.xbongbong.saas.enums.ProjectLogEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.PaymentEnum;
import com.xbongbong.saas.help.SaasCustomerStatementHelper;
import com.xbongbong.saas.help.workflow.PayAndPaymentSheetHelp;
import com.xbongbong.saas.model.CustomerStatementModel;
import com.xbongbong.saas.model.PaymentModel;
import com.xbongbong.saas.service.ConsistencySyncService;
import com.xbongbong.saas.service.CustomerCommunicateService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workflow.domain.entity.WorkflowBackupDataEntity;
import com.xbongbong.workflow.model.WorkflowBackupDataModel;
import com.xbongbong.workflow.pojo.Data;
import com.xbongbong.workflow.pojo.User;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.service.strategy.data.AbstractWorkflowDataStrategy;
import com.xbongbong.workflow.service.strategy.data.WorkflowDataProcessStrategy;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static org.elasticsearch.index.query.QueryBuilders.termQuery;

/**
 *
 * @author 魏荣杰
 *
 */
@Service
@Slf4j
public class WorkflowPaymentStrategy extends AbstractWorkflowDataStrategy implements WorkflowDataProcessStrategy {

    @Resource
    private WorkflowBackupDataModel workflowBackupDataModel;
    @Resource
    private PaymentModel paymentModel;
    @Resource
    private CustomerStatementModel customerStatementModel;
    @Resource
    private FormHelp formHelp;
    @Resource
    private ChartQueryHelp chartQueryHelp;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PayAndPaymentSheetHelp payAndPaymentSheetHelp;
    @Resource
    private ConsistencySyncService consistencySyncService;
    @Resource
    private SaasCustomerStatementHelper saasCustomerStatementHelper;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private UserModel userModel;
    @Resource
    private CustomerCommunicateService customerCommunicateService;

    @Override
    public List<Integer> type() {
        return Collections.singletonList(XbbRefTypeEnum.PAYMENT.getCode());
    }

    @Override
    public void save(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        // 文件柜
        saveDataCabinetFile(workflowTransferPOJO);

        String corpid = workflowTransferPOJO.getCorpid();
        Data pojoData = workflowTransferPOJO.getData();
        Long dataId = pojoData.getId();
        JSONObject data = pojoData.getData();
        Long formId = pojoData.getFormId();

        PaymentEntityExt paymentEntityExt = paymentModel.getByKey(dataId, corpid);

        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains());


        Long originId  = FastJsonHelper.getLongOrDefaultFromFormData(data,PaymentEnum.RECEIVABLES_ORIGIN_ID.getAttr(),0L);
        Integer isRed = FastJsonHelper.getIntegerOrDefaultFromFormData(data,PaymentEnum.RECEIVABLE_IS_RED.getAttr(),0);

        //新增应收款需要插入对账单
        List<PaasFormDataEntityExt> paymentInsertList = Collections.singletonList(paymentEntityExt);
        saasCustomerStatementHelper.save(XbbRefTypeEnum.PAYMENT.getCode(), explainMap, paymentInsertList, null);
        //红冲应收处理
        if(originId > 0L && Objects.equals(isRed,BasicConstant.ONE)){
            //更新原应收款
            PaymentEntityExt originPayment = paymentModel.getByKey(originId, corpid);
            JSONObject originObject = originPayment.getData();
            Double unAmount = FastJsonHelper.getDoubleOrDefaultFromFormData(originObject, PaymentEnum.UN_AMOUNT.getAttr(),0D);
            Double redAmount = FastJsonHelper.getDoubleOrDefaultFromFormData(originObject,PaymentEnum.RED_AMOUNT.getAttr(),0D);
            //现在需要生成的应收金额
            Double amount = FastJsonHelper.getDoubleOrDefaultFromFormData(data, PaymentEnum.AMOUNT.getAttr(),0D);
            //num_3 未收金额 = 应收款-实收金额-坏账金额-丨红冲应收丨
            // 未收金额最新、红冲应收最新
            Double newUnAmount = Arith.sub(unAmount, Math.abs(amount));
            Double newRedAmount = Arith.add(redAmount, amount);
            originObject.put(PaymentEnum.UN_AMOUNT.getAttr(), newUnAmount);
            originObject.put(PaymentEnum.RED_AMOUNT.getAttr(),newRedAmount);
            originObject.put(PaymentEnum.RECEIVABLE_HAS_RED.getAttr(),BasicConstant.ONE);
            //对原应收款的状态的修改
            Double planAmount = FastJsonHelper.getDoubleOrDefaultFromFormData(originObject,PaymentEnum.AMOUNT.getAttr(),0D);
            String paymentStatus = payAndPaymentSheetHelp.handleStatus(planAmount, newUnAmount, 0d, newRedAmount);
            originObject.put(PaymentEnum.STATUS.getAttr(),paymentStatus);
            paymentModel.update(originPayment);
        }

         try {
             if(isNotDistributeBusinessType(workflowTransferPOJO)) {
                 User user = workflowTransferPOJO.getUser();
                 String creatorId = user.getUserId();
                 UserEntity creator = userModel.getByKey(creatorId, corpid);
                 String memo;
                 String communicateMemo;
                 if (Objects.equals(workflowTransferPOJO.getIsImport(), 1)) {
                     memo = CrmLogMemoConstant.DYNAMIC_USER_IMPORT;
                 } else {
                     memo = CrmLogMemoConstant.DYNAMIC_USER_ADD;
                 }
                 PaasFormEntity paasForm = proFormHelp.getPaasForm(pojoData.getFormId(), pojoData.getBusinessType(), corpid);
                 String paasFormName = XbbRefTypeEnum.PAYMENT.getName();
                 if (Objects.nonNull(paasForm)) {
                     paasFormName = paasForm.getName();
                 }
                 String serialNo = paymentEntityExt.getSerialNo();
                 String creatorName = Objects.nonNull(creator) ? creator.getName() : "";
                 communicateMemo = String.format(I18nMessageUtil.getMessage(memo), creatorName, paasFormName, serialNo);

                 CustomerDynamicAddDTO customerDynamicAddDTO = new CustomerDynamicAddDTO();
                 customerDynamicAddDTO.setCorpid(corpid);
                 customerDynamicAddDTO.setUserId(creatorId);
                 customerDynamicAddDTO.setCustomerId(data.getLong(PaymentEnum.CUSTOMER.getAttr()));
                 customerDynamicAddDTO.setContractIds(FastJsonHelper.getTransferTypesFromData(data, PaymentEnum.CONTRACT.getAttr(), Long.class));
                 customerDynamicAddDTO.setMemo(communicateMemo);
                 customerDynamicAddDTO.setCommunicateBusinessText(serialNo);
                 customerDynamicAddDTO.setCommunicateBusinessType(XbbRefTypeEnum.PAYMENT.getCode());
                 customerDynamicAddDTO.setDataId(dataId);
                 customerDynamicAddDTO.setLogType(ProjectLogEnum.PAYMENT_CREATE.getSubType());
                 customerDynamicAddDTO.setPlatform(PlatFormEnum.INTERNAL.getValue());
                 customerCommunicateService.addCustomerDynamic(customerDynamicAddDTO);
             }
         } catch (Exception e) {
             log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowPaymentStrategy.save", e);
         }

        // api
        apiHook(workflowTransferPOJO);
        addLinkDataDynamic(workflowTransferPOJO);
        // log
        afterSaveLog(workflowTransferPOJO);
    }

    @Override
    public void update(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        // 文件柜
        saveDataCabinetFile(workflowTransferPOJO);


        String corpid = workflowTransferPOJO.getCorpid();
        Data pojoData = workflowTransferPOJO.getData();
        Long dataId = pojoData.getId();
        JSONObject data = pojoData.getData();


        //代表是编辑或者覆盖导入, 需要更新tb_customer_statement表中对应的单据的更新时间
        BoolQueryBuilder boolQueryBuilder = chartQueryHelp.boolQueryBuilder4Base(corpid);
        boolQueryBuilder.filter(termQuery(CustomerStatementEnum.SYS_LONG_1.getAttr(), XbbRefTypeEnum.PAYMENT.getCode()));
        List<CustomerStatementEntity> result = formHelp.getFormListByIds4All(IndexTypeEnum.IDX_SAAS_CUSTOMER_STATEMENT,boolQueryBuilder, CustomerStatementEnum.SYS_LONG_2.getAttr(), Arrays.asList(dataId), null, CustomerStatementEntity.class);
        List<CustomerStatementEntity> finalResult = new ArrayList<>();
        result.forEach(customerStatementEntity -> {
            //做一层优化，如果时间一致就不做更新了
            if (!Objects.equals(data.getLong(PaymentEnum.ESTIMATE_TIME.getAttr()), customerStatementEntity.getData().getLong(CustomerStatementEnum.CHECKING_DATE.getAttr()))) {
                customerStatementEntity.getData().put(CustomerStatementEnum.CHECKING_DATE.getAttr(), data.getLong(PaymentEnum.ESTIMATE_TIME.getAttr()));
                customerStatementEntity.setUpdateTime(DateUtil.getNow());
                finalResult.add(customerStatementEntity);
            }
        });
        if (CollectionsUtil.isNotEmpty(finalResult)) {
            customerStatementModel.updateBatch(finalResult, corpid);
        }


        WorkflowBackupDataEntity workflowBackupDataEntity = workflowBackupDataModel.getByKey(workflowTransferPOJO.getBackupDataId(), corpid);


        // 回款计划编号数据一致性同步 目前只有销项发票需要同步
        String serialNo = data.getString(BasicConstant.SERIAL_NO);

        try {
            String oldPaymentSeriNo = workflowBackupDataEntity.getData().getString(BasicConstant.SERIAL_NO);
            if (!Objects.equals(oldPaymentSeriNo, serialNo)) {
                ConsistencySyncRabbitMqDTO consistencySyncRabbitMqDTO = new ConsistencySyncRabbitMqDTO(corpid, dataId, serialNo);
                consistencySyncService.syncPayment(consistencySyncRabbitMqDTO);
            }
        }catch (Exception e){
            log.error("数据一致性同步", e);
        }

        // api
        apiHook(workflowTransferPOJO);
        // log
        afterUpdateLog(workflowTransferPOJO);
    }

    @Override
    public void updateBack(Long taskId, WorkflowTransferPOJO workflowTransferPOJO) {
        // 没有审批无需还原
    }

    @Override
    public void approvalFailed(Long taskId, WorkflowTransferPOJO workflowTransferPOJO, Integer taskType) throws XbbException {
        // 没有审批无需处理
    }
}
